type typ_data = string | number | symbol | 'data';

/**
 * 向 数组 添加 唯一值
 * 添加 成功 返回 true
 * 失败 返回 false
 * @param objSource 数组
 * @param key 欲添加 唯一值
 */
function ObjectOnlyPushSet(objSource: Array<any>, key: any): Boolean;

/**
 * 向 对象 添加 唯一键 及 属性值
 * 添加 成功 返回 true
 * 失败 返回 false
 * @param objSource emptyData 类型 对象
 * @param key 欲添加 的 唯一键
 * @param obj 欲添加 的 值
 * @param data 重指定 data 唯一记录 指定
 */
function ObjectOnlyPushSet<T extends { [key in typ_data]: any }>(
  objSource: T,
  key: typ_data,
  obj?: any,
  data?: typ_data
): Boolean;

function ObjectOnlyPushSet<
  T extends Record<typ_data, any>,
  typ_key extends keyof T
>(
  objSource: Array<any> | T,
  key: any | typ_key,
  obj?: any,
  data?: typ_data
): Boolean {
  // 当 objSource 是 数组 时
  if (Array.isArray(objSource)) {
    if (objSource.includes(key)) {
      return false;
    }
    objSource.push(key);
    return true;
  }

  // 当 objSource 是 emptyData 类型对象 时

  // 初始化 data = 'data'
  data == undefined ? (data = 'data') : undefined;

  // 检测 指定 data 属性 是否 为 数组
  if (!Array.isArray(objSource[data])) {
    //   console.log(`sorry your ${data} is not a available prop`);
    return false;
  }

  if (!objSource[data].includes(key)) {
    objSource[data].push(key);
    if (obj != undefined) {
      objSource[key as typ_key] = obj;
    }
    return true;
  }
  // console.log(`sorry your key:${key} is aready in your Object[${data}]`);
  return false;
}

/**
 * 尝试 删除 数组中的 唯一值
 * 删除 成功 返回 true
 * 失败 返回 false
 * @param objSource 数组
 * @param key 欲删除 唯一值
 */
function removeObjectOnlyPushSet(objSource: Array<any>, key: any): Boolean;

/**
 * 向 对象 删除 唯一键 及 属性值
 * 删除 成功 返回 true
 * 失败 返回 false
 * @param objSource emptyData 类型 对象
 * @param key 欲删除 的 唯一键
 * @param obj 是否 清除 对象 上的 键值 默认 true 删除
 * @param data 重指定 data 唯一记录 指定
 */
function removeObjectOnlyPushSet<T extends { [key in typ_data]: any }>(
  objSource: T,
  key: typ_data,
  obj?: boolean,
  data?: typ_data
): Boolean;

/**
 * 卸载 唯一元素 并解除绑定 值对象
 * -
 * @param {Object | Array} objSource 目标挂载元素
 * @param {String} key 卸载名称
 * @param {boolean} [deleteval = true] 卸载 挂载 的 属性
 * @param {String} data 卸载预定位置 默认为 "data" 需要 该预设位置为 数组
 * @returns {boolean}
 */
function removeObjectOnlyPushSet<
  T extends Record<typ_data, any>,
  typ_key extends keyof T
>(
  objSource: Array<any> | T,
  key: any | typ_key,
  deleteval?: boolean,
  data?: typ_data
): Boolean {
  let ind;
  if (Array.isArray(objSource)) {
    ind = objSource.indexOf(key);
    if (ind >= -1) {
      objSource.splice(ind, 1);
      return true;
    }
    return false;
    // console.log(`sorry your key:${key} is not in your Array`);
  }

  // 当 objSource 是 emptyData 类型对象 时

  // 初始化 data = 'data'
  data == undefined ? (data = 'data') : undefined;

  // 初始化 deleteval = true
  deleteval == undefined ? (deleteval = true) : undefined;

  // 检测 指定 data 属性 是否 为 数组
  if (!Array.isArray(objSource[data])) {
    //   console.log(`sorry your ${data} is not a available prop`);
    return false;
  }

  ind = objSource[data].indexOf(key);

  if (ind > -1) {
    objSource[data].splice(ind, 1);
    if (deleteval == true) {
      delete objSource[key];
    }
    return true;
  }
  // console.log(`sorry your key:${key} is aready in your Object[${data}]`);
  return false;
}

export { ObjectOnlyPushSet, removeObjectOnlyPushSet };
